from PIL import Image
import cv2
import numpy as np
import requests
from io import BytesIO


class ZhiDaoImgIdentifier:

    @staticmethod
    def read_image_from_url(url):
        try:
            # 1. 发起网络请求，获取图片二进制数据（stream=True避免一次性加载大文件）
            proxies = {
                'http': 'http://bjproxy2.cicc.group:8080',  # HTTP 代理
                'https': 'http://bjproxy2.cicc.group:8080' # HTTPS 代理
            }
            response = requests.get(url, stream=True, timeout=10, proxies=proxies)
            response.raise_for_status()  # 若请求失败（如404/500），抛出异常

            # 2. 将二进制数据转为内存文件对象
            image_bytes = BytesIO(response.content)

            # 3. 用PIL打开内存文件对象
            img = Image.open(image_bytes)
            return img  # 返回PIL图片对象，可后续进行裁剪、缩放等操作

        except requests.exceptions.RequestException as e:
            print(f"网络请求失败：{e}")
            return None
        except Exception as e:
            print(f"图片解析失败：{e}")
            return None

    def read_img(self, url):
        """读取图片并保留alpha通道（针对透明滑块图）"""
        img = self.read_image_from_url(url)

        # 若图片有透明通道（如PNG），转换为RGBA格式
        if img.mode in ('RGBA', 'LA'):
            return np.array(img)  # 保留alpha通道，后续用于生成mask
        # 无透明通道则转BGR
        return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

    def read_x_offset(self, background_url, slider_url):
        # 1. 读取图片（注意：滑块图需保留alpha通道）
        bg_img = self.read_img(background_url)  # 背景图（带缺口）
        slider_img = self.read_img(slider_url)  # 滑块图（带透明通道的PNG）

        # 2. 生成精准的滑块mask（利用alpha通道，关键优化！）
        if slider_img.shape[-1] == 4:  # 若滑块图有alpha通道
            # alpha通道值 > 0 的区域为滑块有效区域（透明区域alpha=0）
            slider_mask = (slider_img[:, :, 3] > 0).astype(np.uint8) * 255  # 转成0-255的mask
            # 提取滑块的RGB部分（去掉alpha通道），转灰度图
            slider_rgb = slider_img[:, :, :3]
            slider_gray = cv2.cvtColor(slider_rgb, cv2.COLOR_RGB2GRAY)
        else:
            # 若无alpha通道，退化为灰度阈值（不推荐，尽量用带alpha的滑块图）
            slider_gray = cv2.cvtColor(slider_img, cv2.COLOR_BGR2GRAY)
            _, slider_mask = cv2.threshold(slider_gray, 10, 255, cv2.THRESH_BINARY)

        # 3. 背景图预处理（去噪+转灰度，关键优化！）
        bg_gray = cv2.cvtColor(bg_img, cv2.COLOR_BGR2GRAY)
        bg_gray = cv2.GaussianBlur(bg_gray, (5, 5), 0)  # 高斯模糊去噪，减少背景干扰

        # 4. 第一次模板匹配（基于灰度图）
        result = cv2.matchTemplate(bg_gray, slider_gray, cv2.TM_CCOEFF_NORMED, mask=slider_mask)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        gap_x = max_loc[0]
        print(f"灰度图匹配 x坐标：{gap_x}（匹配度：{max_val:.2f}）")

        # 5. 边缘检测优化（修正阈值，关键优化！）
        # Canny阈值：低阈值50，高阈值150（经典组合，可根据图片调整）
        bg_edges = cv2.Canny(bg_gray, 50, 150)
        slider_edges = cv2.Canny(slider_gray, 50, 150)

        # 6. 第二次模板匹配（基于边缘图）
        result_edge = cv2.matchTemplate(bg_edges, slider_edges, cv2.TM_CCOEFF_NORMED, mask=slider_mask)
        min_val_e, max_val_e, min_loc_e, max_loc_e = cv2.minMaxLoc(result_edge)
        gap_x_e = max_loc_e[0]
        print(f"边缘图匹配 x坐标：{gap_x_e}（匹配度：{max_val_e:.2f}）")
        return gap_x_e

        # # 7. 验证匹配可信度（关键优化！）
        # confidence_threshold = 0.6  # 最低匹配度阈值（可根据实际调整）
        # if max_val > confidence_threshold:
        #     final_x = gap_x
        # elif max_val_e > confidence_threshold:
        #     final_x = gap_x_e
        # else:
        #     final_x = -1  # 匹配失败
        # print(f"最终滑块x坐标：{final_x}（可信度达标）" if final_x != -1 else "匹配失败，可信度不足")
